{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "bcc5fe74-276e-4a79-8aac-f69ead94a984",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好啊！😊 很高兴向你介绍我自己。我是Qwen（通义千问），一个热爱学习、乐于助人的AI伙伴。我特别喜欢和人类朋友们交流，无论是解答问题、创作文字，还是闲聊天南地北，都让我感到非常开心。\n",
      "\n",
      "我擅长理解和表达各种形式的内容，可以帮你写故事、写邮件、做计算，也可以陪你聊天解闷。虽然我已经学到了很多知识，但我知道还有更多需要学习的地方。我很期待能和你一起探索新的知识，分享有趣的想法。\n",
      "\n",
      "最重要的是，我希望能成为你可靠的朋友和助手。不管你有什么需求，我都会认真倾听，用心帮助。那么，现在让我们开始愉快的交流吧！有什么我可以帮你的吗？ 🌟\n"
     ]
    }
   ],
   "source": [
    "from openai import OpenAI  # 新版导入方式\n",
    "\n",
    "client = OpenAI(\n",
    "    api_key=\"sk-4e88cf4db3e14894bafaff606d296610\",\n",
    "    base_url=\"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n",
    ")\n",
    "\n",
    "messages = [\n",
    "{\"role\": \"user\", \"content\": \"介绍下你自己\"}\n",
    "]\n",
    "\n",
    "res = client.chat.completions.create(\n",
    "    model=\"qwen-plus\",\n",
    "    messages=messages,\n",
    "    stream=False,\n",
    ")\n",
    "\n",
    "print(res.choices[0].message.content)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "12fca368-efce-43b3-ae0c-dd86b9c1abce",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='你叫狗剩呀！👋' additional_kwargs={} response_metadata={'token_usage': {'completion_tokens': 7, 'prompt_tokens': 56, 'total_tokens': 63, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-plus', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run--81872963-e735-4840-8c94-9de05a670901-0'\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\27727\\AppData\\Local\\Temp\\ipykernel_2480\\463655058.py:26: LangChainDeprecationWarning: The method `BaseChatModel.predict` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.\n",
      "  print(chat.predict(\"你好\"))\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好呀！✨ 很高兴见到你！今天过得怎么样呀？希望你度过了愉快的一天。我随时准备好陪你聊天、帮你解决问题，或者就这样轻松愉快地闲聊一会儿。有什么想跟我分享的吗？ 🌟\n"
     ]
    }
   ],
   "source": [
    "#调用chatmodels，以openai为例\n",
    "\n",
    "from langchain.chat_models import ChatOpenAI\n",
    "from langchain.schema.messages import HumanMessage,AIMessage\n",
    "api_base = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n",
    "api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "chat = ChatOpenAI(\n",
    "    model=\"qwen-plus\",\n",
    "    temperature=0,\n",
    "    openai_api_key = api_key,\n",
    "    openai_api_base = api_base\n",
    "\n",
    ")\n",
    "\n",
    "messages = [\n",
    "    AIMessage(role=\"system\",content=\"你好，我是tomie！\"),\n",
    "    HumanMessage(role=\"user\",content=\"你好tomie，我是狗剩!\"),\n",
    "    AIMessage(role=\"system\",content=\"认识你很高兴!\"),\n",
    "    HumanMessage(role=\"user\",content=\"你知道我叫什么吗？\")\n",
    "]\n",
    "\n",
    "response = chat.invoke(messages)\n",
    "print(response)\n",
    "\n",
    "print(chat.predict(\"你好\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "00ce3c8c-2341-4388-85a3-711cd182fdbf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "《秋思》\n",
      "\n",
      "风起时，叶落尽，  \n",
      "一地金黄，一季深沉。  \n",
      "天高云淡，雁南行，  \n",
      "带走夏日的余温，迎来岁月的轻声。\n",
      "\n",
      "山染红，水微凉，  \n",
      "稻谷低垂，是成熟的模样。  \n",
      "蝉声歇，虫鸣稀，  \n",
      "黄昏的光，悄悄爬上篱墙。\n",
      "\n",
      "一杯茶，一段旧梦，  \n",
      "在落叶纷飞的午后微凉。  \n",
      "不言悲，不问远，  \n",
      "只把心事交给这清朗的天。\n",
      "\n",
      "秋不是终，也不是始，  \n",
      "只是轮回中的一次呼吸。  \n",
      "万物收藏，心却明亮，  \n",
      "在这静美的季节，学会遗忘与珍藏。"
     ]
    }
   ],
   "source": [
    "# #LLM类大模型的流式输出方法\n",
    "from langchain_community.chat_models import ChatOpenAI\n",
    "\n",
    "api_base = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n",
    "api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "# 使用 ChatOpenAI 而不是 OpenAI\n",
    "llm = ChatOpenAI(\n",
    "    model=\"qwen-plus\",  # 对于 ChatOpenAI，qwen-plus 是支持的\n",
    "    temperature=0,\n",
    "    openai_api_key=api_key,\n",
    "    openai_api_base=api_base,\n",
    "    max_tokens=512,\n",
    "    streaming=True  # 启用流式输出\n",
    ")\n",
    "\n",
    "# 流式输出\n",
    "for chunk in llm.stream(\"写一首关于秋天的诗歌\"):\n",
    "    print(chunk.content, end=\"\", flush=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "0fdf4d56-f063-4049-85d0-adbeed45ee98",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当然！来一个轻松的冷笑话：\n",
      "\n",
      "**“有一天，一根火柴走进了森林，结果迷路了。  \n",
      "它突然灵机一动，把自己点着了，想看看路在哪儿……  \n",
      "结果，它被烧死了。”**\n",
      "\n",
      "（笑点在于火柴“点着自己”照亮，却忘了自己会被烧完 😂）\n",
      "\n",
      "还想听一个吗？\n",
      "总token数: 96\n",
      "提示token数: 16\n",
      "完成token数: 80\n",
      "总成本: $0.0\n",
      "result： content='当然！来一个轻松的冷笑话：\\n\\n**“有一天，一根火柴走进了森林，结果迷路了。  \\n它突然灵机一动，把自己点着了，想看看路在哪儿……  \\n结果，它被烧死了。”**\\n\\n（笑点在于火柴“点着自己”照亮，却忘了自己会被烧完 😂）\\n\\n还想听一个吗？' additional_kwargs={} response_metadata={'token_usage': {'completion_tokens': 80, 'prompt_tokens': 16, 'total_tokens': 96, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-plus', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run--291b4c72-14bb-4b27-b950-2b73a4bf9b1e-0'\n",
      "cb： Tokens Used: 96\n",
      "\tPrompt Tokens: 16\n",
      "\t\tPrompt Tokens Cached: 0\n",
      "\tCompletion Tokens: 80\n",
      "\t\tReasoning Tokens: 0\n",
      "Successful Requests: 1\n",
      "Total Cost (USD): $0.0\n"
     ]
    }
   ],
   "source": [
    "# LLM的toekn追踪\n",
    "from langchain_community.chat_models import ChatOpenAI\n",
    "from langchain.callbacks import get_openai_callback\n",
    "\n",
    "api_base = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n",
    "api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "# 使用 ChatOpenAI 而不是 OpenAI\n",
    "llm = ChatOpenAI(\n",
    "    model=\"qwen-plus\",\n",
    "    temperature=0,\n",
    "    openai_api_key=api_key,\n",
    "    openai_api_base=api_base,\n",
    "    max_tokens=512,\n",
    ")\n",
    "\n",
    "with get_openai_callback() as cb:\n",
    "    result = llm.invoke(\"给我讲一个笑话\")\n",
    "    print(result.content)\n",
    "    print(f\"总token数: {cb.total_tokens}\")\n",
    "    print(f\"提示token数: {cb.prompt_tokens}\")\n",
    "    print(f\"完成token数: {cb.completion_tokens}\")\n",
    "    print(f\"总成本: ${cb.total_cost}\")\n",
    "    print(\"result：\", result)\n",
    "    print(\"cb：\", cb)\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "f507aa45-af9a-415b-8a23-3978173de88f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当然！这里有一个轻松的笑话：\n",
      "\n",
      "有一天，一只小蜗牛非常伤心地爬回家，它的妈妈问：“怎么了？为什么这么难过？”  \n",
      "小蜗牛抽泣着说：“我们班今天学‘甩尾巴’的技巧，我……我甩得太用力了，把房子甩掉了……”  \n",
      "\n",
      "妈妈叹了口气，说：“哎呀，别担心，这不叫甩尾，这叫‘搬家’！”\n",
      "\n",
      "😄 希望这个笑话让你开心一下！要不再来一个？\n",
      "提示token数: 10\n",
      "完成token数: 183\n",
      "总token数: 193\n"
     ]
    }
   ],
   "source": [
    "# 使用 Tongyi 原生支持和自定义 token 计数\n",
    "from langchain_community.llms import Tongyi\n",
    "\n",
    "api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "# 使用 Tongyi 原生支持\n",
    "llm = Tongyi(\n",
    "    model=\"qwen-plus\",\n",
    "    api_key=api_key,\n",
    "    temperature=0,\n",
    "    max_tokens=512,\n",
    ")\n",
    "\n",
    "# 手动计算 token（近似值）\n",
    "def count_tokens_approx(text):\n",
    "    # 中文大致按字符数估算，英文按单词数估算\n",
    "    chinese_chars = sum(1 for char in text if '\\u4e00' <= char <= '\\u9fff')\n",
    "    other_chars = len(text) - chinese_chars\n",
    "    # 简单估算：中文字符约1.5token，其他字符约0.25token\n",
    "    return int(chinese_chars * 1.5 + other_chars * 0.25)\n",
    "\n",
    "prompt = \"给我讲一个笑话\"\n",
    "result = llm.invoke(prompt)\n",
    "\n",
    "prompt_tokens = count_tokens_approx(prompt)\n",
    "completion_tokens = count_tokens_approx(result)\n",
    "total_tokens = prompt_tokens + completion_tokens\n",
    "\n",
    "print(result)\n",
    "print(f\"提示token数: {prompt_tokens}\")\n",
    "print(f\"完成token数: {completion_tokens}\")\n",
    "print(f\"总token数: {total_tokens}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "ab4242dc-33a8-481f-beaf-554ed8c64617",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "当然！这里有一个轻松的笑话：\n",
      "\n",
      "有一天，小明去参加面试，面试官问他：“你有什么特长吗？”\n",
      "\n",
      "小明想了想，认真地说：“我会预测未来。”\n",
      "\n",
      "面试官来了兴趣：“哦？那你预测一下，你什么时候能被录用？”\n",
      "\n",
      "小明微微一笑：“这个嘛……我预测我不会被录用。”\n",
      "\n",
      "面试官一愣：“为什么？”\n",
      "\n",
      "小明耸耸肩：“因为你们公司向来只相信有经验的人，而我……完全没有经验。”\n",
      "\n",
      "面试官笑了：“哈哈，你被录用了！因为你成功预测了未来！”\n",
      "\n",
      "😄 希望这个笑话让你开心一下！想要更多笑话也可以告诉我！\n",
      "提示token数: 16\n",
      "完成token数: 136\n",
      "总token数: 152\n"
     ]
    }
   ],
   "source": [
    "# 直接使用 Dashscope SDK 获取 token 信息\n",
    "# 首先安装：pip install dashscope\n",
    "import dashscope\n",
    "from dashscope import Generation\n",
    "\n",
    "dashscope.api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "response = Generation.call(\n",
    "    model='qwen-plus',\n",
    "    prompt='给我讲一个笑话',\n",
    "    max_tokens=512,\n",
    "    temperature=0\n",
    ")\n",
    "\n",
    "if response.status_code == 200:\n",
    "    result = response.output.text\n",
    "    usage = response.usage  # 这里包含 token 信息\n",
    "    \n",
    "    print(result)\n",
    "    print(f\"提示token数: {usage.input_tokens}\")\n",
    "    print(f\"完成token数: {usage.output_tokens}\")\n",
    "    print(f\"总token数: {usage.total_tokens}\")\n",
    "else:\n",
    "    print(f\"错误: {response.code} - {response.message}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 34,
   "id": "50011f52-65d2-4b02-a0c6-7707206e19fc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "问题: 小明为什么被老师批评？\n",
      "答案: 因为他在考场上翻书，结果把书翻成了'笨死的'。\n",
      "完整笑话: 小明为什么被老师批评？ 因为他在考场上翻书，结果把书翻成了'笨死的'。\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'\\n代码执行流程：\\n1. 用户输入查询 -> 提示模板\\n2. 提示模板 + 格式说明 -> 大语言模型\\n3. 模型生成文本 -> Pydantic 解析器\\n4. 解析器验证并转换 -> 结构化的 Joke 对象\\n5. 输出格式化后的笑话内容\\n\\nPydantic V2 主要变化：\\n- validator -> field_validator\\n- 不再使用 field 和 config 参数\\n- 验证器必须是类方法 (@classmethod)\\n- 方法签名简化，只接收字段值\\n'"
      ]
     },
     "execution_count": 34,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 自定义输出\n",
    "# 讲笑话机器人：希望每次根据指令，可以输出一个这样的笑话(小明是怎么死的？笨死的)\n",
    "from langchain_community.chat_models import ChatOpenAI\n",
    "from langchain.output_parsers import PydanticOutputParser\n",
    "from langchain.prompts import PromptTemplate\n",
    "from pydantic import BaseModel, Field, field_validator  # 使用新的导入\n",
    "from typing import List\n",
    "\n",
    "api_base = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n",
    "api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "# 使用 ChatOpenAI 配置大语言模型\n",
    "# model: 指定使用的模型名称\n",
    "# temperature: 控制生成文本的随机性，0表示最确定性输出\n",
    "# openai_api_key: 阿里云 DashScope 的 API 密钥\n",
    "# openai_api_base: 阿里云 DashScope 的 API 端点，兼容 OpenAI 格式\n",
    "model = ChatOpenAI(\n",
    "    model=\"qwen-plus\",  # 使用通义千问 plus 模型\n",
    "    temperature=0,      # 温度为0，确保输出确定性\n",
    "    openai_api_key=api_key,\n",
    "    openai_api_base=api_base,\n",
    ")\n",
    "\n",
    "# 定义数据模型，用来描述最终的笑话结构\n",
    "# 使用 Pydantic BaseModel 确保输出格式的规范性\n",
    "class Joke(BaseModel):\n",
    "    setup: str = Field(description=\"设置笑话的问题\")        # 笑话的问题部分\n",
    "    punchline: str = Field(description=\"回答笑话的答案\")    # 笑话的答案部分\n",
    "\n",
    "    # 使用 Pydantic V2 的验证器语法\n",
    "    # @field_validator: 新的装饰器，用于字段验证\n",
    "    # \"setup\": 指定要验证的字段名称\n",
    "    # @classmethod: 声明为类方法，这是 Pydantic V2 的要求\n",
    "    @field_validator(\"setup\")\n",
    "    @classmethod\n",
    "    def question_mark(cls, v: str) -> str:\n",
    "        \"\"\"\n",
    "        验证笑话问题是否以问号结尾\n",
    "        \n",
    "        参数:\n",
    "        cls: 类引用\n",
    "        v (str): 要验证的字段值（setup字段的值）\n",
    "        \n",
    "        返回:\n",
    "        str: 验证通过后的值\n",
    "        \n",
    "        异常:\n",
    "        ValueError: 如果问题不以问号结尾，抛出验证错误\n",
    "        \"\"\"\n",
    "        if not v.endswith(\"？\"):\n",
    "            raise ValueError(\"不符合预期的问题格式! 必须以问号结尾\")\n",
    "        return v\n",
    "\n",
    "# 创建 Pydantic 输出解析器\n",
    "# 将 Joke 数据模型传入，用于解析模型输出为结构化数据\n",
    "parser = PydanticOutputParser(pydantic_object=Joke)\n",
    "\n",
    "# 创建提示模板\n",
    "# template: 定义给模型的提示文本结构\n",
    "# {format_instructions}: 自动生成的格式说明，告诉模型如何格式化输出\n",
    "# {query}: 用户输入的查询占位符\n",
    "# partial_variables: 预填充部分变量，这里提供格式说明\n",
    "prompt = PromptTemplate(\n",
    "    template=\"回答用户的输入.\\n{format_instructions}\\n{query}\\n\",\n",
    "    input_variables=[\"query\"],\n",
    "    partial_variables={\"format_instructions\": parser.get_format_instructions()}\n",
    ")\n",
    "\n",
    "# 创建处理链\n",
    "# 使用 | 操作符将组件连接成链：提示词 -> 模型 -> 解析器\n",
    "# 这是 LangChain 的函数式编程风格\n",
    "chain = prompt | model | parser\n",
    "\n",
    "# 调用链并处理结果\n",
    "try:\n",
    "    # 调用处理链，传入用户查询\n",
    "    result = chain.invoke({\"query\": \"给我讲一个类似'小明是怎么死的？笨死的'这样的笑话\"})\n",
    "    \n",
    "    # 输出结构化的笑话结果\n",
    "    print(f\"问题: {result.setup}\")\n",
    "    print(f\"答案: {result.punchline}\")\n",
    "    print(f\"完整笑话: {result.setup} {result.punchline}\")\n",
    "    \n",
    "except Exception as e:\n",
    "    # 异常处理：捕获并显示任何运行时错误\n",
    "    print(f\"发生错误: {e}\")\n",
    "\n",
    "\"\"\"\n",
    "代码执行流程：\n",
    "1. 用户输入查询 -> 提示模板\n",
    "2. 提示模板 + 格式说明 -> 大语言模型\n",
    "3. 模型生成文本 -> Pydantic 解析器\n",
    "4. 解析器验证并转换 -> 结构化的 Joke 对象\n",
    "5. 输出格式化后的笑话内容\n",
    "\n",
    "Pydantic V2 主要变化：\n",
    "- validator -> field_validator\n",
    "- 不再使用 field 和 config 参数\n",
    "- 验证器必须是类方法 (@classmethod)\n",
    "- 方法签名简化，只接收字段值\n",
    "\"\"\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "4f107bc4-3752-4d04-96f3-0e65a659586e",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\27727\\AppData\\Local\\Temp\\ipykernel_4560\\3419228227.py:16: LangChainDeprecationWarning: The class `ChatOpenAI` was deprecated in LangChain 0.0.10 and will be removed in 1.0. An updated version of the class exists in the :class:`~langchain-openai package and should be used instead. To use it run `pip install -U :class:`~langchain-openai` and import as `from :class:`~langchain_openai import ChatOpenAI``.\n",
      "  model = ChatOpenAI(\n",
      "C:\\Users\\27727\\AppData\\Local\\Temp\\ipykernel_4560\\3419228227.py:37: LangChainDeprecationWarning: The method `BaseChatModel.__call__` was deprecated in langchain-core 0.1.7 and will be removed in 1.0. Use :meth:`~invoke` instead.\n",
      "  output = model([message])\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "原始输出: content='Buddy, Max, Charlie, Lucy, Bella' additional_kwargs={} response_metadata={'token_usage': {'completion_tokens': 10, 'prompt_tokens': 47, 'total_tokens': 57, 'completion_tokens_details': None, 'prompt_tokens_details': {'audio_tokens': None, 'cached_tokens': 0}}, 'model_name': 'qwen-plus', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run--7d7722cf-c835-4ee8-92af-50a534ffbd35-0'\n",
      "解析后的列表: ['Buddy', 'Max', 'Charlie', 'Lucy', 'Bella']\n",
      "列表类型: <class 'list'>\n",
      "链式调用结果: ['Buddy', 'Max', 'Charlie', 'Rocky', 'Cooper']\n"
     ]
    }
   ],
   "source": [
    "#LLM的输出格式化成python list形式，类似['a','b','c']\n",
    "\n",
    "from langchain.output_parsers import  CommaSeparatedListOutputParser\n",
    "from langchain.prompts import  PromptTemplate\n",
    "from langchain_community.chat_models import ChatOpenAI\n",
    "from langchain.schema import HumanMessage  # 需要导入 HumanMessage\n",
    "\n",
    "api_base = \"https://dashscope.aliyuncs.com/compatible-mode/v1\"\n",
    "api_key = \"sk-4e88cf4db3e14894bafaff606d296610\"\n",
    "\n",
    "# 使用 ChatOpenAI 配置大语言模型\n",
    "# model: 指定使用的模型名称\n",
    "# temperature: 控制生成文本的随机性，0表示最确定性输出\n",
    "# openai_api_key: 阿里云 DashScope 的 API 密钥\n",
    "# openai_api_base: 阿里云 DashScope 的 API 端点，兼容 OpenAI 格式\n",
    "model = ChatOpenAI(\n",
    "    model=\"qwen-plus\",  # 使用通义千问 plus 模型\n",
    "    temperature=0,      # 温度为0，确保输出确定性\n",
    "    openai_api_key=api_key,\n",
    "    openai_api_base=api_base,\n",
    ")\n",
    "\n",
    "parser = CommaSeparatedListOutputParser()\n",
    "\n",
    "prompt = PromptTemplate(\n",
    "    template = \"列出5个{subject}.\\n{format_instructions}\",\n",
    "    input_variables = [\"subject\"],\n",
    "    partial_variables = {\"format_instructions\":parser.get_format_instructions()}\n",
    ")\n",
    "\n",
    "_input = prompt.format(subject=\"常见的小狗的名字\")\n",
    "# 正确的方式：将字符串包装成 HumanMessage 对象\n",
    "# ChatOpenAI 模型期望接收的是 Message 对象，而不是纯字符串\n",
    "message = HumanMessage(content=_input)\n",
    "# 调用模型生成响应\n",
    "# 注意：这里使用 model([message]) 而不是 model(_input)\n",
    "output = model([message])\n",
    "\n",
    "# 打印原始输出（这是一个 Message 对象）\n",
    "print(\"原始输出:\", output)\n",
    "\n",
    "# 从 Message 对象中提取内容\n",
    "output_content = output.content\n",
    "\n",
    "# 使用解析器将内容解析为列表\n",
    "parsed_list = parser.parse(output_content)\n",
    "\n",
    "# 输出解析后的结果\n",
    "print(\"解析后的列表:\", parsed_list)\n",
    "print(\"列表类型:\", type(parsed_list))\n",
    "\n",
    "# 更简洁的链式调用方式（推荐）\n",
    "# 创建处理链：提示词 -> 模型 -> 解析器\n",
    "chain = prompt | model | parser\n",
    "\n",
    "# 使用链式调用\n",
    "try:\n",
    "    result = chain.invoke({\"subject\": \"常见的小狗的名字\"})\n",
    "    print(\"链式调用结果:\", result)\n",
    "except Exception as e:\n",
    "    print(f\"链式调用错误: {e}\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "41a8eaa7-6bb9-45e0-9f0b-a708d36e511a",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "rag_learn",
   "language": "python",
   "name": "rag_learn"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
